﻿using System.Collections.Concurrent;
using AutoMapper;
using HelenServer.FileStorage.Contracts;
using HelenServer.Grpc.Contracts;

namespace HelenServer.FileStorage.Services;

[Injection(typeof(IFSNotifySpliderRange))]
public class FSNotifySpliderRange : GrpcMethod<IEnumerable<NotifySpiderGrpcModel>, GrpcResult<IReadOnlyCollection<int>>>, IFSNotifySpliderRange
{
    private readonly IFileStorageService _service;
    private readonly IMapper _mapper;
    private readonly HttpClient _httpClient;

    public FSNotifySpliderRange(IFileStorageService service, IMapper mapper, HttpClient httpClient)
    {
        _service = service;
        _mapper = mapper;
        _httpClient = httpClient;
    }

    public override async Task<GrpcResult<IReadOnlyCollection<int>>> InvokeAsync(IEnumerable<NotifySpiderGrpcModel> request, ServerCallContext context)
    {
        var spiders = _mapper.Map<IEnumerable<NotifySpiderGrpcModel>, IEnumerable<NotifySpiderModel>>(request);

        _httpClient.DefaultRequestHeaders.Add("Authorization", context.RequestHeaders.GetString("zt_authorization"));

        var box = new ConcurrentBag<UploadModel>();

        await Parallel.ForEachAsync(
            spiders,
            context.CancellationToken,
            async (spider, cancellationToken) =>
            {
                var buffer = await _httpClient.GetByteArrayAsync(spider.Url, cancellationToken);

                var model = new UploadModel
                {
                    Name = spider.Name,
                    Extension = spider.Extension,
                    AddedBy = spider.AddedBy,
                    Buffer = buffer,
                };

                box.Add(model);
            });

        var operation = context.GetHttpContext().GetOperation(box.ToList().AsEnumerable());

        var result = await _service.UploadFileRangeAsync(operation, context.CancellationToken);

        return result.Succeed
            ? result.ToGrpcResult(r => r)
            : OperationResult<IReadOnlyCollection<int>>.Failed("批量上传失败").ToGrpcResult<IReadOnlyCollection<int>>();
    }
}